﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace SpicIE.Controls
{
    /// <summary>
    /// Creates a new entry in the context menu with a specific user defined behaviour
    /// </summary>
    public abstract class ContextMenu : IControlBase
    {
        /// <summary>
        /// The PluginGuid _must_ be a unique GUID to identify and register the COM object correctly
        /// </summary>
        public abstract string PluginGuid { get; }
        /// <summary>
        /// The PluginProgID _must_ be provided to identify and register the COM object correctly
        /// </summary>
        public abstract string PluginProgID { get; }

        #region Member variables declaration

        protected string MenuText;
        protected string MenuCommand;
        protected ContextEnum MenuContext = ContextEnum.Default;

        private Guid ContextMenuID { get { return new Guid(PluginGuid); } }
        private string ContextMenuProgID { get { return PluginProgID; } }

        [ComVisible(false)]
        public ContextEnum ContextMenuContext { get { return MenuContext; } }
        public string ContextMenuText { get { return MenuText; } }
        public string ContextMenuCommand { get { return MenuCommand; } }
        
        #endregion

        /// <summary>
        /// appearance of the context menu
        /// </summary>
        public enum ContextEnum
        {
            Default = 0x1,
            Images = 0x2,
            Controls = 0x4,
            Tables = 0x8,
            TextSelection = 0x10,
            Anchor = 0x20
        } ;

        #region Context menu constructor
        /// <summary>
        /// global constructor
        /// </summary>
        public ContextMenu()
        {
            
        }

        /// <summary>
        /// Constructor for creating a new context menu
        /// </summary>
        /// <param name="menuText">the text which is displayed in the menu</param>
        /// <param name="menuCommand">the command which will be executed</param>
        /// <param name="menuContext">the type of context the menu should be</param>
        public ContextMenu(string menuText, string menuCommand, ContextEnum menuContext)
        {
            MenuText = menuText;
            MenuCommand = menuCommand;
            MenuContext = menuContext;
        }
        #endregion

        #region COM object register functionality
        /// <summary>
        /// global function for registering the com object
        /// </summary>
        public void Register()
        {
            try
            {
                if (String.IsNullOrEmpty(ContextMenuText))
                    return;

                Host.RegisterCOMObject(GetType(), ContextMenuID, ContextMenuProgID);

                RegistryKey mainKey = Registry.CurrentUser.CreateSubKey(Constants.REGISTRY_MENUEXTENSIONS + ContextMenuText);
                mainKey.SetValue(null, ContextMenuCommand);

                if (ContextMenuContext > 0)
                {
                    RegistryKey contextKey =
                        Registry.CurrentUser.CreateSubKey(Constants.REGISTRY_MENUEXTENSIONS + ContextMenuText + "\\Contexts");
                    contextKey.SetValue(null, ContextMenuContext, RegistryValueKind.DWord);
                }

                RegistryKey flagKey = Registry.CurrentUser.CreateSubKey(Constants.REGISTRY_MENUEXTENSIONS + ContextMenuText + "\\Flags");
                flagKey.SetValue(null, 0x1, RegistryValueKind.DWord);

                Host.TraceSink.TraceInformation("SpicIE: Registering Context Menu " + ContextMenuText);
            }
            catch(Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception: Registering ContextMenu " + ContextMenuText + ": " + ex);
            }
        }

        /// <summary>
        /// global function for unregistering the com object
        /// </summary>
        public void Unregister()
        {
            try
            {
                Host.UnRegisterCOMObject(ContextMenuID);

                if (Registry.CurrentUser.OpenSubKey(Constants.REGISTRY_MENUEXTENSIONS + ContextMenuText) != null)
                    Registry.CurrentUser.DeleteSubKeyTree(Constants.REGISTRY_MENUEXTENSIONS + ContextMenuText);

                Host.TraceSink.TraceInformation("SpicIE: Unregistering Context Menu " + ContextMenuText);
            }
            catch(Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception: Unregistering ContextMenu " + ContextMenuText + ": " + ex);
            }
        }
        #endregion
    }
}
